
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $NoKeywords: $
//
//===========================================================================//

// NOTE: old_bf_read is guaranteed to return zeros if it overflows.

#ifndef BITBUF_H
#define BITBUF_H

#ifdef _WIN32
#pragma once
#endif

#if !defined(BUILD_DEBUG)
# if defined(NDEBUG)
#  define BUILD_DEBUG 0
# elif defined(_DEBUG)
#  define BUILD_DEBUG 1
# else
#  pragma error Could not determine BUILD_DEBUG value
# endif
#endif

#include "tier0/platform.h"

#ifndef MIN
#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
#endif
#pragma warning(push)
#pragma warning (disable: 4267)
//-----------------------------------------------------------------------------
// You can define a handler function that will be called in case of 
// out-of-range values and overruns here.
//
// NOTE: the handler is only called in debug mode.
//
// Call SetBitBufErrorHandler to install a handler.
//-----------------------------------------------------------------------------

typedef enum
{
	BITBUFERROR_VALUE_OUT_OF_RANGE = 0,		// Tried to write a value with too few bits.
	BITBUFERROR_BUFFER_OVERRUN,				// Was about to overrun a buffer.

	BITBUFERROR_NUM_ERRORS
} BitBufErrorType;


typedef void (*BitBufErrorHandler)(BitBufErrorType errorType, const char* pDebugName);


#if BUILD_DEBUG
extern void InternalBitBufErrorHandler(BitBufErrorType errorType, const char* pDebugName);
#define CallErrorHandler( errorType, pDebugName ) InternalBitBufErrorHandler( errorType, pDebugName );
#else
#define CallErrorHandler( errorType, pDebugName )
#endif


// Use this to install the error handler. Call with NULL to uninstall your error handler.
void SetBitBufErrorHandler(BitBufErrorHandler fn);


//-----------------------------------------------------------------------------
// Helpers.
//-----------------------------------------------------------------------------

inline int BitByte(int bits)
{
	// return PAD_NUMBER( bits, 8 ) >> 3;
	return (bits + 7) >> 3;
}

//-----------------------------------------------------------------------------
enum EBitCoordType
{
	kCW_None,
	kCW_LowPrecision,
	kCW_Integral
};

//-----------------------------------------------------------------------------
// namespaced helpers
//-----------------------------------------------------------------------------
namespace bitbuf
{
	// ZigZag Transform:  Encodes signed integers so that they can be
	// effectively used with varint encoding.
	//
	// varint operates on unsigned integers, encoding smaller numbers into
	// fewer bytes.  If you try to use it on a signed integer, it will treat
	// this number as a very large unsigned integer, which means that even
	// small signed numbers like -1 will take the maximum number of bytes
	// (10) to encode.  ZigZagEncode() maps signed integers to unsigned
	// in such a way that those with a small absolute value will have smaller
	// encoded values, making them appropriate for encoding using varint.
	//
	//       int32 ->     uint32
	// -------------------------
	//           0 ->          0
	//          -1 ->          1
	//           1 ->          2
	//          -2 ->          3
	//         ... ->        ...
	//  2147483647 -> 4294967294
	// -2147483648 -> 4294967295
	//
	//        >> encode >>
	//        << decode <<

	inline uint32 ZigZagEncode32(int32 n)
	{
		// Note:  the right-shift must be arithmetic
		return(n << 1) ^ (n >> 31);
	}

	inline int32 ZigZagDecode32(uint32 n)
	{
		return(n >> 1) ^ -static_cast<int32>(n & 1);
	}

	inline uint64 ZigZagEncode64(int64 n)
	{
		// Note:  the right-shift must be arithmetic
		return(n << 1) ^ (n >> 63);
	}

	inline int64 ZigZagDecode64(uint64 n)
	{
		return(n >> 1) ^ -static_cast<int64>(n & 1);
	}

	const int kMaxVarintBytes = 10;
	const int kMaxVarint32Bytes = 5;
}

//-----------------------------------------------------------------------------
// Used for serialization
//-----------------------------------------------------------------------------

class bf_write
{
public:
	bf_write();

	// nMaxBits can be used as the number of bits in the buffer. 
	// It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
	bf_write(void* pData, int nBytes, int nMaxBits = -1);
	bf_write(const char* pDebugName, void* pData, int nBytes, int nMaxBits = -1);

	// Start writing to the specified buffer.
	// nMaxBits can be used as the number of bits in the buffer. 
	// It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
	void			StartWriting(void* pData, int nBytes, int iStartBit = 0, int nMaxBits = -1);

	// Restart buffer writing.
	void			Reset();

	// Get the base pointer.
	unsigned char* GetBasePointer() { return m_pData; }

	// Enable or disable assertion on overflow. 99% of the time, it's a bug that we need to catch,
	// but there may be the occasional buffer that is allowed to overflow gracefully.
	void			SetAssertOnOverflow(bool bAssert);

	// This can be set to assign a name that gets output if the buffer overflows.
	const char* GetDebugName();
	void			SetDebugName(const char* pDebugName);


	// Seek to a specific position.
public:

	void			SeekToBit(int bitPos);


	// Bit functions.
public:

	void			WriteOneBit(int nValue);
	void			WriteOneBitNoCheck(int nValue);
	void			WriteOneBitAt(int iBit, int nValue);

	// Write signed or unsigned. Range is only checked in debug.
	void			WriteUBitLong(unsigned int data, int numbits, bool bCheckRange = true);
	void			WriteSBitLong(int data, int numbits);

	// Tell it whether or not the data is unsigned. If it's signed,
	// cast to unsigned before passing in (it will cast back inside).
	void			WriteBitLong(unsigned int data, int numbits, bool bSigned);

	// Write a list of bits in.
	bool			WriteBits(const void* pIn, int nBits);

	// writes an unsigned integer with variable bit length
	void			WriteUBitVar(unsigned int data);

	// writes a varint encoded integer
	void			WriteVarInt32(uint32 data);
	void			WriteVarInt64(uint64 data);
	void			WriteSignedVarInt32(int32 data);
	void			WriteSignedVarInt64(int64 data);
	int				ByteSizeVarInt32(uint32 data);
	int				ByteSizeVarInt64(uint64 data);
	int				ByteSizeSignedVarInt32(int32 data);
	int				ByteSizeSignedVarInt64(int64 data);

	// Copy the bits straight out of pIn. This seeks pIn forward by nBits.
	// Returns an error if this buffer or the read buffer overflows.
	bool			WriteBitsFromBuffer(class bf_read* pIn, int nBits);

	void			WriteBitAngle(float fAngle, int numbits);
	void			WriteBitCoord(const float f);
	void			WriteBitCoordMP(const float f, EBitCoordType coordType);
	void 			WriteBitCellCoord(const float f, int bits, EBitCoordType coordType);
	void			WriteBitFloat(float val);
	void			WriteBitNormal(float f);

	// Byte functions.
public:

	void			WriteChar(int val);
	void			WriteByte(unsigned int val);
	void			WriteShort(int val);
	void			WriteWord(unsigned int val);
	void			WriteLong(int32 val);
	void			WriteLongLong(int64 val);
	void			WriteFloat(float val);
	bool			WriteBytes(const void* pBuf, int nBytes);

	// Returns false if it overflows the buffer.
	bool			WriteString(const char* pStr);
	bool			WriteString(const wchar_t* pStr);


	// Status.
public:

	// How many bytes are filled in?
	int				GetNumBytesWritten() const;
	int				GetNumBitsWritten() const;
	int				GetMaxNumBits() const;
	int				GetNumBitsLeft() const;
	int				GetNumBytesLeft() const;
	unsigned char* GetData();
	const unsigned char* GetData() const;

	// Has the buffer overflowed?
	bool			CheckForOverflow(int nBits);
	inline bool		IsOverflowed() const { return m_bOverflow; }

	inline void		SetOverflowFlag();

public:
	// The current buffer.
	unsigned char* m_pData;
	int				m_nDataBytes;
	int				m_nDataBits;

	// Where we are in the buffer.
	int				m_iCurBit;

public:

	// Errors?
	bool			m_bOverflow;

	bool			m_bAssertOnOverflow;
	const char* m_pDebugName;
};
static_assert(sizeof(bf_write) == 32);
static_assert(offsetof(bf_write, m_pData) == 0);
static_assert(offsetof(bf_write, m_nDataBytes) == 8);
static_assert(offsetof(bf_write, m_nDataBits) == 12);
static_assert(offsetof(bf_write, m_iCurBit) == 16);
static_assert(offsetof(bf_write, m_bOverflow) == 20);
static_assert(offsetof(bf_write, m_bAssertOnOverflow) == 21);
static_assert(offsetof(bf_write, m_pDebugName) == 24);

//-----------------------------------------------------------------------------
// Inlined methods
//-----------------------------------------------------------------------------

// How many bytes are filled in?
inline int bf_write::GetNumBytesWritten() const
{
	return BitByte(m_iCurBit);
}

inline int bf_write::GetNumBitsWritten() const
{
	return m_iCurBit;
}

inline int bf_write::GetMaxNumBits() const
{
	return m_nDataBits;
}

inline int bf_write::GetNumBitsLeft() const
{
	return m_nDataBits - m_iCurBit;
}

inline int bf_write::GetNumBytesLeft() const
{
	return GetNumBitsLeft() >> 3;
}

inline unsigned char* bf_write::GetData()
{
	return m_pData;
}

inline const unsigned char* bf_write::GetData() const
{
	return m_pData;
}

inline bool bf_write::CheckForOverflow(int nBits)
{
	if (m_iCurBit + nBits > m_nDataBits)
	{
		SetOverflowFlag();
		CallErrorHandler(BITBUFERROR_BUFFER_OVERRUN, GetDebugName());
	}

	return m_bOverflow;
}

inline void bf_write::SetOverflowFlag()
{
	if (m_bAssertOnOverflow)
	{
		//Assert( false );
	}

	m_bOverflow = true;
}

inline void bf_write::WriteOneBitNoCheck(int nValue)
{
	if (nValue)
		m_pData[m_iCurBit >> 3] |= (1 << (m_iCurBit & 7));
	else
		m_pData[m_iCurBit >> 3] &= ~(1 << (m_iCurBit & 7));

	++m_iCurBit;
}

inline void bf_write::WriteOneBit(int nValue)
{
	if (!CheckForOverflow(1))
		WriteOneBitNoCheck(nValue);
}


inline void	bf_write::WriteOneBitAt(int iBit, int nValue)
{
	if (iBit + 1 > m_nDataBits)
	{
		SetOverflowFlag();
		CallErrorHandler(BITBUFERROR_BUFFER_OVERRUN, GetDebugName());
		return;
	}

	if (nValue)
		m_pData[iBit >> 3] |= (1 << (iBit & 7));
	else
		m_pData[iBit >> 3] &= ~(1 << (iBit & 7));
}


inline void bf_write::WriteUBitLong(unsigned int curData, int numbits, bool bCheckRange)
{
#if BUILD_DEBUG
	// Make sure it doesn't overflow.
	if (bCheckRange && numbits < 32)
	{
		if (curData >= (uint32)(1 << numbits))
		{
			CallErrorHandler(BITBUFERROR_VALUE_OUT_OF_RANGE, GetDebugName());
		}
	}
	//Assert( numbits >= 0 && numbits <= 32 );
#endif

	extern uint32 g_BitWriteMasks[32][33];

	// Bounds checking..
	if ((m_iCurBit + numbits) > m_nDataBits)
	{
		m_iCurBit = m_nDataBits;
		SetOverflowFlag();
		CallErrorHandler(BITBUFERROR_BUFFER_OVERRUN, GetDebugName());
		return;
	}

	int nBitsLeft = numbits;
	int iCurBit = m_iCurBit;

	// Mask in a dword.
	unsigned int iDWord = iCurBit >> 5;
	//Assert( (iDWord*4 + sizeof(int32)) <= (unsigned int)m_nDataBytes );

	uint32 iCurBitMasked = iCurBit & 31;

	uint32 dword = LoadLittleDWord((uint32*)m_pData, iDWord);

	dword &= g_BitWriteMasks[iCurBitMasked][nBitsLeft];
	dword |= curData << iCurBitMasked;

	// write to stream (lsb to msb ) properly
	StoreLittleDWord((uint32*)m_pData, iDWord, dword);

	// Did it span a dword?
	int nBitsWritten = 32 - iCurBitMasked;
	if (nBitsWritten < nBitsLeft)
	{
		nBitsLeft -= nBitsWritten;
		curData >>= nBitsWritten;

		// read from stream (lsb to msb) properly 
		dword = LoadLittleDWord((uint32*)m_pData, iDWord + 1);

		dword &= g_BitWriteMasks[0][nBitsLeft];
		dword |= curData;

		// write to stream (lsb to msb) properly 
		StoreLittleDWord((uint32*)m_pData, iDWord + 1, dword);
	}

	m_iCurBit += numbits;
}


//-----------------------------------------------------------------------------
// This is useful if you just want a buffer to write into on the stack.
//-----------------------------------------------------------------------------

template<int SIZE>
class old_bf_write_static : public bf_write
{
public:
	inline old_bf_write_static() : bf_write(m_StaticData, SIZE) {}

	char	m_StaticData[SIZE];
};



//-----------------------------------------------------------------------------
// Used for unserialization
//-----------------------------------------------------------------------------

class old_bf_read
{
public:
	old_bf_read();

	// nMaxBits can be used as the number of bits in the buffer. 
	// It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
	old_bf_read(const void* pData, int nBytes, int nBits = -1);
	old_bf_read(const char* pDebugName, const void* pData, int nBytes, int nBits = -1);

	// Start reading from the specified buffer.
	// pData's start address must be dword-aligned.
	// nMaxBits can be used as the number of bits in the buffer. 
	// It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
	void			StartReading(const void* pData, int nBytes, int iStartBit = 0, int nBits = -1);

	// Restart buffer reading.
	void			Reset();

	// Enable or disable assertion on overflow. 99% of the time, it's a bug that we need to catch,
	// but there may be the occasional buffer that is allowed to overflow gracefully.
	void			SetAssertOnOverflow(bool bAssert);

	// This can be set to assign a name that gets output if the buffer overflows.
	const char* GetDebugName();
	void			SetDebugName(const char* pName);

	void			ExciseBits(int startbit, int bitstoremove);


	// Bit functions.
public:

	// Returns 0 or 1.
	int				ReadOneBit();


protected:

	unsigned int	CheckReadUBitLong(int numbits);		// For debugging.
	int				ReadOneBitNoCheck();				// Faster version, doesn't check bounds and is inlined.
	bool			CheckForOverflow(int nBits);


public:

	// Get the base pointer.
	const unsigned char* GetBasePointer() { return m_pData; }

	FORCEINLINE int TotalBytesAvailable(void) const
	{
		return m_nDataBytes;
	}

	// Read a list of bits in..
	void            ReadBits(void* pOut, int nBits);

	float			ReadBitAngle(int numbits);

	unsigned int	ReadUBitLong(int numbits);
	unsigned int	PeekUBitLong(int numbits);
	int				ReadSBitLong(int numbits);

	// reads an unsigned integer with variable bit length
	unsigned int	ReadUBitVar();

	// reads a varint encoded integer
	uint32			ReadVarInt32();
	uint64			ReadVarInt64();
	int32			ReadSignedVarInt32();
	int64			ReadSignedVarInt64();

	// You can read signed or unsigned data with this, just cast to 
	// a signed int if necessary.
	unsigned int	ReadBitLong(int numbits, bool bSigned);

	float			ReadBitCoord();
	float			ReadBitCoordMP(EBitCoordType coordType);
	float 			ReadBitCellCoord(int bits, EBitCoordType coordType);
	float			ReadBitFloat();
	float			ReadBitNormal();


	// Byte functions (these still read data in bit-by-bit).
public:

	int				ReadChar();
	int				ReadByte();
	int				ReadShort();
	int				ReadWord();
	int32			ReadLong();
	int64			ReadLongLong();
	float			ReadFloat();
	bool			ReadBytes(void* pOut, int nBytes);

	// Returns false if bufLen isn't large enough to hold the
	// string in the buffer.
	//
	// Always reads to the end of the string (so you can read the
	// next piece of data waiting).
	//
	// If bLine is true, it stops when it reaches a '\n' or a null-terminator.
	//
	// pStr is always null-terminated (unless bufLen is 0).
	//
	// pOutNumChars is set to the number of characters left in pStr when the routine is 
	// complete (this will never exceed bufLen-1).
	//
	bool			ReadString(char* pStr, int bufLen, bool bLine = false, int* pOutNumChars = NULL);
	bool			ReadWString(wchar_t* pStr, int bufLen, bool bLine = false, int* pOutNumChars = NULL);

	// Reads a string and allocates memory for it. If the string in the buffer
	// is > 2048 bytes, then pOverflow is set to true (if it's not NULL).
	char* ReadAndAllocateString(bool* pOverflow = 0);

	// Status.
public:
	int				GetNumBytesLeft();
	int				GetNumBytesRead();
	int				GetNumBitsLeft();
	int				GetNumBitsRead() const;

	// Has the buffer overflowed?
	inline bool		IsOverflowed() const { return m_bOverflow; }

	inline bool		Seek(int iBit);					// Seek to a specific bit.
	inline bool		SeekRelative(int iBitDelta);	// Seek to an offset from the current position.

	// Called when the buffer is overflowed.
	inline void		SetOverflowFlag();


public:

	// The current buffer.
	const unsigned char* m_pData;
	int						m_nDataBytes;
	int						m_nDataBits;

	// Where we are in the buffer.
	int				m_iCurBit;


private:
	// used by varbit reads internally
	inline int CountRunOfZeros();

	// Errors?
	bool			m_bOverflow;

	// For debugging..
	bool			m_bAssertOnOverflow;

	const char* m_pDebugName;
};

//-----------------------------------------------------------------------------
// Inlines.
//-----------------------------------------------------------------------------

inline int old_bf_read::GetNumBytesRead()
{
	return BitByte(m_iCurBit);
}

inline int old_bf_read::GetNumBitsLeft()
{
	return m_nDataBits - m_iCurBit;
}

inline int old_bf_read::GetNumBytesLeft()
{
	return GetNumBitsLeft() >> 3;
}

inline int old_bf_read::GetNumBitsRead() const
{
	return m_iCurBit;
}

inline void old_bf_read::SetOverflowFlag()
{
	if (m_bAssertOnOverflow)
	{
		//Assert( false );
	}

	m_bOverflow = true;
}

inline bool old_bf_read::Seek(int iBit)
{
	if (iBit < 0 || iBit > m_nDataBits)
	{
		SetOverflowFlag();
		m_iCurBit = m_nDataBits;
		return false;
	}
	else
	{
		m_iCurBit = iBit;
		return true;
	}
}

// Seek to an offset from the current position.
inline bool	old_bf_read::SeekRelative(int iBitDelta)
{
	return Seek(m_iCurBit + iBitDelta);
}

inline bool old_bf_read::CheckForOverflow(int nBits)
{
	if (m_iCurBit + nBits > m_nDataBits)
	{
		SetOverflowFlag();
		CallErrorHandler(BITBUFERROR_BUFFER_OVERRUN, GetDebugName());
	}

	return m_bOverflow;
}

inline int old_bf_read::ReadOneBitNoCheck()
{
	int value = m_pData[m_iCurBit >> 3] & (1 << (m_iCurBit & 7));
	++m_iCurBit;
	return !!value;
}

inline int old_bf_read::ReadOneBit()
{
	return (!CheckForOverflow(1)) ? ReadOneBitNoCheck() : 0;
}

inline float old_bf_read::ReadBitFloat()
{
	int32 val;

	//Assert(sizeof(float) == sizeof(int32));
	//Assert(sizeof(float) == 4);

	if (CheckForOverflow(32))
		return 0.0f;

	int bit = m_iCurBit & 0x7;
	int byte = m_iCurBit >> 3;
	val = m_pData[byte] >> bit;
	val |= ((int)m_pData[byte + 1]) << (8 - bit);
	val |= ((int)m_pData[byte + 2]) << (16 - bit);
	val |= ((int)m_pData[byte + 3]) << (24 - bit);
	if (bit != 0)
		val |= ((int)m_pData[byte + 4]) << (32 - bit);
	m_iCurBit += 32;
	return *((float*)&val);
}


inline unsigned int old_bf_read::ReadUBitLong(int numbits)
{
	extern uint32 g_ExtraMasks[32];

	if ((m_iCurBit + numbits) > m_nDataBits)
	{
		m_iCurBit = m_nDataBits;
		SetOverflowFlag();
		return 0;
	}

	//Assert( numbits > 0 && numbits <= 32 );

	// Read the current dword.
	int idword1 = m_iCurBit >> 5;
	unsigned int dword1 = LoadLittleDWord((uint32*)m_pData, idword1);

	dword1 >>= (m_iCurBit & 31); // Get the bits we're interested in.

	m_iCurBit += numbits;
	unsigned int ret = dword1;

	// Does it span this dword?
	if ((m_iCurBit - 1) >> 5 == idword1)
	{
		if (numbits != 32)
			ret &= g_ExtraMasks[numbits];
	}
	else
	{
		int nExtraBits = m_iCurBit & 31;
		unsigned int dword2 = LoadLittleDWord((uint32*)m_pData, idword1 + 1);

		dword2 &= g_ExtraMasks[nExtraBits];

		// No need to mask since we hit the end of the dword.
		// Shift the second dword's part into the high bits.
		ret |= (dword2 << (numbits - nExtraBits));
	}

	return ret;
}


class CBitBuffer
{
public:
	char const* m_pDebugName;
	bool m_bOverflow;
	size_t m_nDataBits;
	size_t m_nDataBytes;

	void SetDebugName(char const* pName)
	{
		m_pDebugName = pName;
	}

	CBitBuffer(void)
	{
		m_bOverflow = false;
		m_pDebugName = NULL;
		m_nDataBits = -1;
		m_nDataBytes = 0;
	}

	FORCEINLINE void SetOverflowFlag(void)
	{
		m_bOverflow = true;
	}

	FORCEINLINE bool IsOverflowed(void) const
	{
		return m_bOverflow;
	}

	static const uint32 s_nMaskTable[33];							// 0 1 3 7 15 ..

};
static_assert(sizeof(CBitBuffer) == 32);
static_assert(offsetof(CBitBuffer, m_pDebugName) == 0);
static_assert(offsetof(CBitBuffer, m_bOverflow) == 8);
static_assert(offsetof(CBitBuffer, m_nDataBits) == 16);
static_assert(offsetof(CBitBuffer, m_nDataBytes) == 24);

class CBitWrite : public CBitBuffer
{
	uint32 m_nOutBufWord;
	int m_nOutBitsAvail;
	uint32* m_pDataOut;
	uint32* m_pBufferEnd;
	uint32* m_pData;
	bool m_bFlushed;

public:
	void StartWriting(void* pData, int nBytes, int iStartBit = 0, int nMaxBits = -1);


	CBitWrite(void* pData, int nBytes, int nBits = -1)
	{
		m_bFlushed = false;
		StartWriting(pData, nBytes, 0, nBits);
	}

	CBitWrite(const char* pDebugName, void* pData, int nBytes, int nBits = -1)
	{
		m_bFlushed = false;
		SetDebugName(pDebugName);
		StartWriting(pData, nBytes, 0, nBits);
	}

	CBitWrite(void)
	{
		m_bFlushed = false;
	}

	~CBitWrite(void)
	{
		TempFlush();
		//Assert( (! m_pData ) || m_bFlushed );
	}
	FORCEINLINE int GetNumBitsLeft(void) const
	{
		return m_nOutBitsAvail + (32 * (m_pBufferEnd - m_pDataOut - 1));
	}

	FORCEINLINE void Reset(void)
	{
		m_bOverflow = false;
		m_nOutBitsAvail = 32;
		m_pDataOut = m_pData;
		m_nOutBufWord = 0;

	}

	FORCEINLINE void TempFlush(void)
	{
		// someone wants to know how much data we have written, or the pointer to it, so we'd better make
		// sure we write our data
		if (m_nOutBitsAvail != 32)
		{
			if (m_pDataOut == m_pBufferEnd)
			{
				SetOverflowFlag();
			}
			else
			{
				StoreLittleDWord(m_pDataOut, 0, LoadLittleDWord(m_pDataOut, 0) & ~s_nMaskTable[32 - m_nOutBitsAvail] | m_nOutBufWord);
			}
		}
		m_bFlushed = true;
	}

	FORCEINLINE unsigned char* GetBasePointer()
	{
		TempFlush();
		return reinterpret_cast<unsigned char*>(m_pData);
	}

	FORCEINLINE unsigned char* GetData()
	{
		return GetBasePointer();
	}

	FORCEINLINE void Finish();
	FORCEINLINE void Flush();
	FORCEINLINE void FlushNoCheck();
	FORCEINLINE void WriteOneBit(int nValue);
	FORCEINLINE void WriteOneBitNoCheck(int nValue);
	FORCEINLINE void WriteUBitLong(unsigned int data, int numbits, bool bCheckRange = true);
	FORCEINLINE void WriteSBitLong(int data, int numbits);
	FORCEINLINE void WriteUBitVar(unsigned int data);
	FORCEINLINE void WriteBitFloat(float flValue);
	FORCEINLINE void WriteFloat(float flValue);
	bool WriteBits(const void* pInData, int nBits);
	void WriteBytes(const void* pBuf, int nBytes);
	void SeekToBit(int nSeekPos);

	FORCEINLINE int GetNumBitsWritten(void) const
	{
		return (32 - m_nOutBitsAvail) + (32 * (m_pDataOut - m_pData));
	}

	FORCEINLINE int GetNumBytesWritten(void) const
	{
		return (GetNumBitsWritten() + 7) >> 3;
	}


	FORCEINLINE void WriteLong(int32 val)
	{
		WriteSBitLong(val, 32);
	}



	FORCEINLINE void WriteChar(int val)
	{
		WriteSBitLong(val, sizeof(char) << 3);
	}

	FORCEINLINE void WriteByte(int val)
	{
		WriteUBitLong(val, sizeof(unsigned char) << 3, false);
	}

	FORCEINLINE void WriteShort(int val)
	{
		WriteSBitLong(val, sizeof(short) << 3);
	}

	FORCEINLINE void WriteWord(int val)
	{
		WriteUBitLong(val, sizeof(unsigned short) << 3);
	}

	bool WriteString(const char* pStr);
	bool WriteString(const wchar_t* pStr);

	void WriteLongLong(int64 val);

	void WriteBitAngle(float fAngle, int numbits);
	void WriteBitCoord(const float f);
	void WriteBitCoordMP(const float f, EBitCoordType coordType);
	void WriteBitCellCoord(const float f, int bits, EBitCoordType coordType);
	//void WriteBitVec3Coord( const Vector& fa );
	void WriteBitNormal(float f);
	//void WriteBitVec3Normal( const Vector& fa );
	//void WriteBitAngles( const QAngle& fa );

	// Copy the bits straight out of pIn. This seeks pIn forward by nBits.
	// Returns an error if this buffer or the read buffer overflows.
	bool WriteBitsFromBuffer(class bf_read* pIn, int nBits);

};

void CBitWrite::Finish(void)
{
	if (m_nOutBitsAvail != 32)
	{
		if (m_pDataOut == m_pBufferEnd)
		{
			SetOverflowFlag();
		}
		StoreLittleDWord(m_pDataOut, 0, m_nOutBufWord);
	}
}

void CBitWrite::FlushNoCheck(void)
{
	StoreLittleDWord(m_pDataOut++, 0, m_nOutBufWord);
	m_nOutBitsAvail = 32;
	m_nOutBufWord = 0;										// ugh - I need this because of 32 bit writes. a<<=32 is a nop

}
void CBitWrite::Flush(void)
{
	if (m_pDataOut == m_pBufferEnd)
	{
		SetOverflowFlag();
	}
	else
	{
		StoreLittleDWord(m_pDataOut++, 0, m_nOutBufWord);
	}
	m_nOutBufWord = 0;										// ugh - I need this because of 32 bit writes. a<<=32 is a nop
	m_nOutBitsAvail = 32;

}
void CBitWrite::WriteOneBitNoCheck(int nValue)
{
	m_nOutBufWord |= (nValue & 1) << (32 - m_nOutBitsAvail);
	if (--m_nOutBitsAvail == 0)
	{
		FlushNoCheck();
	}
}

void CBitWrite::WriteOneBit(int nValue)
{
	m_nOutBufWord |= (nValue & 1) << (32 - m_nOutBitsAvail);
	if (--m_nOutBitsAvail == 0)
	{
		Flush();
	}
}

FORCEINLINE void CBitWrite::WriteUBitLong(unsigned int nData, int nNumBits, bool bCheckRange)
{

#ifdef BUILD_DEBUG
	// Make sure it doesn't overflow.
	if (bCheckRange && nNumBits < 32)
	{
		//Assert( nData <= (uint32)(1 << nNumBits ) );
	}
	//Assert( nNumBits >= 0 && nNumBits <= 32 );
#endif
	if (nNumBits <= m_nOutBitsAvail)
	{
		if (bCheckRange)
			m_nOutBufWord |= (nData) << (32 - m_nOutBitsAvail);
		else
			m_nOutBufWord |= (nData & s_nMaskTable[nNumBits]) << (32 - m_nOutBitsAvail);
		m_nOutBitsAvail -= nNumBits;
		if (m_nOutBitsAvail == 0)
		{
			Flush();
		}
	}
	else
	{
		// split dwords case
		int nOverflowBits = (nNumBits - m_nOutBitsAvail);
		m_nOutBufWord |= (nData & s_nMaskTable[m_nOutBitsAvail]) << (32 - m_nOutBitsAvail);
		Flush();
		m_nOutBufWord = (nData >> (nNumBits - nOverflowBits));
		m_nOutBitsAvail = 32 - nOverflowBits;
	}
}

FORCEINLINE void CBitWrite::WriteSBitLong(int nData, int nNumBits)
{
	WriteUBitLong((uint32)nData, nNumBits, false);
}

FORCEINLINE void CBitWrite::WriteUBitVar(unsigned int n)
{
	if (n < 16)
		WriteUBitLong(n, 6);
	else
		if (n < 256)
			WriteUBitLong((n & 15) | 16 | ((n & (128 | 64 | 32 | 16)) << 2), 10);
		else
			if (n < 4096)
				WriteUBitLong((n & 15) | 32 | ((n & (2048 | 1024 | 512 | 256 | 128 | 64 | 32 | 16)) << 2), 14);
			else
			{
				WriteUBitLong((n & 15) | 48, 6);
				WriteUBitLong((n >> 4), 32 - 4);
			}
}

FORCEINLINE void CBitWrite::WriteBitFloat(float flValue)
{
	WriteUBitLong(*((uint32*)&flValue), 32);
}

FORCEINLINE void CBitWrite::WriteFloat(float flValue)
{
	// Pre-swap the float, since WriteBits writes raw data
	LittleFloat(&flValue, &flValue);
	WriteUBitLong(*((uint32*)&flValue), 32);
}

class CBitRead : public CBitBuffer
{
public:
	uint32 m_nInBufWord;
	int m_nBitsAvail;
	uint32 const* m_pDataIn;
	uint32 const* m_pBufferEnd;
	uint32 const* m_pData;

public:
	CBitRead(const void* pData, int nBytes, int nBits = -1)
	{
		StartReading(pData, nBytes, 0, nBits);
	}

	CBitRead(const char* pDebugName, const void* pData, int nBytes, int nBits = -1)
	{
		SetDebugName(pDebugName);
		StartReading(pData, nBytes, 0, nBits);
	}

	CBitRead(void) : CBitBuffer()
	{
	}

	FORCEINLINE int Tell(void) const
	{
		return GetNumBitsRead();
	}

	FORCEINLINE size_t TotalBytesAvailable(void) const
	{
		return m_nDataBytes;
	}

	FORCEINLINE int GetNumBitsLeft() const
	{
		return m_nDataBits - Tell();
	}

	FORCEINLINE int GetNumBytesLeft() const
	{
		return GetNumBitsLeft() >> 3;
	}

	bool Seek(int nPosition);

	FORCEINLINE bool SeekRelative(int nOffset)
	{
		return Seek(GetNumBitsRead() + nOffset);
	}

	FORCEINLINE unsigned char const* GetBasePointer()
	{
		return reinterpret_cast<unsigned char const*>(m_pData);
	}

	void StartReading(const void* pData, int nBytes, int iStartBit = 0, int nBits = -1);

	FORCEINLINE int GetNumBitsRead(void) const;
	FORCEINLINE int GetNumBytesRead(void) const;

	FORCEINLINE void GrabNextDWord(bool bOverFlowImmediately = false);
	FORCEINLINE void FetchNext(void);
	FORCEINLINE unsigned int ReadUBitLong(int numbits);
	FORCEINLINE int ReadSBitLong(int numbits);
	FORCEINLINE unsigned int ReadUBitVar(void);
	FORCEINLINE unsigned int PeekUBitLong(int numbits);
	FORCEINLINE float ReadBitFloat(void);
	float ReadBitCoord();
	float ReadBitCoordMP(EBitCoordType coordType);
	float ReadBitCellCoord(int bits, EBitCoordType coordType);
	float ReadBitNormal();
	bool ReadBytes(void* pOut, int nBytes);
	float ReadBitAngle(int numbits);

	// Returns 0 or 1.
	FORCEINLINE int	ReadOneBit(void);
	FORCEINLINE int ReadLong(void);
	FORCEINLINE int ReadChar(void);
	FORCEINLINE int ReadByte(void);
	FORCEINLINE int ReadShort(void);
	FORCEINLINE int ReadWord(void);
	FORCEINLINE float ReadFloat(void);
	void ReadBits(void* pOut, int nBits);

	int ReadBitsClamped_ptr(void* pOutData, size_t outSizeBytes, size_t nBits);

	template <typename T, size_t N>
	FORCEINLINE int ReadBitsClamped(T(&pOut)[N], size_t nBits) {
		return ReadBitsClamped_ptr(pOut, N * sizeof(T), nBits);
	}

	// Returns false if bufLen isn't large enough to hold the
	// string in the buffer.
	//
	// Always reads to the end of the string (so you can read the
	// next piece of data waiting).
	//
	// If bLine is true, it stops when it reaches a '\n' or a null-terminator.
	//
	// pStr is always null-terminated (unless bufLen is 0).
	//
	// pOutN<umChars is set to the number of characters left in pStr when the routine is 
	// complete (this will never exceed bufLen-1).
	//
	bool ReadString(char* pStr, int bufLen, bool bLine = false, int* pOutNumChars = NULL);
	bool ReadWString(OUT_Z_CAP(maxLenInChars) wchar_t* pStr, int maxLenInChars, bool bLine = false, int* pOutNumChars = NULL);
	char* ReadAndAllocateString(bool* pOverflow = 0);

	int64 ReadLongLong(void);

	// reads a varint encoded integer
	uint32			ReadVarInt32();
	uint64			ReadVarInt64();
	int32			ReadSignedVarInt32() { return bitbuf::ZigZagDecode32(ReadVarInt32()); }
	int64			ReadSignedVarInt64() { return bitbuf::ZigZagDecode64(ReadVarInt64()); }
};
static_assert(sizeof(CBitRead) == 32 + 32);
static_assert(offsetof(CBitRead, m_nInBufWord) == 32);
static_assert(offsetof(CBitRead, m_nBitsAvail) == 36);
static_assert(offsetof(CBitRead, m_pDataIn) == 40);
static_assert(offsetof(CBitRead, m_pBufferEnd) == 48);
static_assert(offsetof(CBitRead, m_pData) == 56);


FORCEINLINE int CBitRead::GetNumBitsRead(void) const
{
	if (!m_pData)									   // pesky null ptr bitbufs. these happen.
		return 0;

	int nCurOfs = int(((intp(m_pDataIn) - intp(m_pData)) / 4) - 1);
	nCurOfs *= 32;
	nCurOfs += (32 - m_nBitsAvail);
	int nAdjust = 8 * (m_nDataBytes & 3);
	return MIN(nCurOfs + nAdjust, m_nDataBits);
}

FORCEINLINE int CBitRead::GetNumBytesRead(void) const
{
	return ((GetNumBitsRead() + 7) >> 3);
}

FORCEINLINE void CBitRead::GrabNextDWord(bool bOverFlowImmediately)
{
	if (m_pDataIn == m_pBufferEnd)
	{
		m_nBitsAvail = 1;									// so that next read will run out of words
		m_nInBufWord = 0;
		m_pDataIn++;										// so seek count increments like old
		if (bOverFlowImmediately)
			SetOverflowFlag();
	}
	else
		if (m_pDataIn > m_pBufferEnd)
		{
			SetOverflowFlag();
			m_nInBufWord = 0;
		}
		else
		{
			//Assert( reinterpret_cast<intp>(m_pDataIn) + 3 < reinterpret_cast<intp>(m_pBufferEnd));
			m_nInBufWord = LittleDWord(*(m_pDataIn++));
		}
}

FORCEINLINE void CBitRead::FetchNext(void)
{
	m_nBitsAvail = 32;
	GrabNextDWord(false);
}

int CBitRead::ReadOneBit(void)
{
	int nRet = m_nInBufWord & 1;
	if (--m_nBitsAvail == 0)
	{
		FetchNext();
	}
	else
		m_nInBufWord >>= 1;
	return nRet;
}


unsigned int CBitRead::ReadUBitLong(int numbits)
{
	if (m_nBitsAvail >= numbits)
	{
		unsigned int nRet = m_nInBufWord & s_nMaskTable[numbits];
		m_nBitsAvail -= numbits;
		if (m_nBitsAvail)
		{
			m_nInBufWord >>= numbits;
		}
		else
		{
			FetchNext();
		}
		return nRet;
	}
	else
	{
		// need to merge words
		unsigned int nRet = m_nInBufWord;
		numbits -= m_nBitsAvail;
		GrabNextDWord(true);
		if (m_bOverflow)
			return 0;
		nRet |= ((m_nInBufWord & s_nMaskTable[numbits]) << m_nBitsAvail);
		m_nBitsAvail = 32 - numbits;
		m_nInBufWord >>= numbits;
		return nRet;
	}
}

FORCEINLINE unsigned int CBitRead::PeekUBitLong(int numbits)
{
	int nSaveBA = m_nBitsAvail;
	int nSaveW = m_nInBufWord;
	uint32 const* pSaveP = m_pDataIn;
	unsigned int nRet = ReadUBitLong(numbits);
	m_nBitsAvail = nSaveBA;
	m_nInBufWord = nSaveW;
	m_pDataIn = pSaveP;
	return nRet;
}

FORCEINLINE int CBitRead::ReadSBitLong(int numbits)
{
	int nRet = ReadUBitLong(numbits);
	// sign extend
	return (nRet << (32 - numbits)) >> (32 - numbits);
}

FORCEINLINE int CBitRead::ReadLong(void)
{
	return (int)ReadUBitLong(sizeof(int32) << 3);
}

FORCEINLINE float CBitRead::ReadFloat(void)
{
	uint32 nUval = ReadUBitLong(sizeof(int32) << 3);
	return *((float*)&nUval);
}

#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable : 4715)								// disable warning on not all cases
// returning a value. throwing default:
// in measurably reduces perf in bit
// packing benchmark
#endif
FORCEINLINE unsigned int CBitRead::ReadUBitVar(void)
{
	unsigned int ret = ReadUBitLong(6);
	switch (ret & (16 | 32))
	{
	case 16:
		ret = (ret & 15) | (ReadUBitLong(4) << 4);
		//Assert( ret >= 16);
		break;

	case 32:
		ret = (ret & 15) | (ReadUBitLong(8) << 4);
		//Assert( ret >= 256);
		break;
	case 48:
		ret = (ret & 15) | (ReadUBitLong(32 - 4) << 4);
		//Assert( ret >= 4096 );
		break;
	}
	return ret;
}
#ifdef _WIN32
#pragma warning(pop)
#endif

FORCEINLINE float CBitRead::ReadBitFloat(void)
{
	uint32 nvalue = ReadUBitLong(32);
	return *((float*)&nvalue);
}

int CBitRead::ReadChar(void)
{
	return ReadSBitLong(sizeof(char) << 3);
}

int CBitRead::ReadByte(void)
{
	return ReadUBitLong(sizeof(unsigned char) << 3);
}

int CBitRead::ReadShort(void)
{
	return ReadSBitLong(sizeof(short) << 3);
}

int CBitRead::ReadWord(void)
{
	return ReadUBitLong(sizeof(unsigned short) << 3);
}

#define WRAP_READ( bc ) 																									  \
class bf_read : public bc																									  \
{																															  \
public:																														  \
    FORCEINLINE bf_read( void ) : bc(  )																								  \
	{																														  \
	}																														  \
																															  \
	FORCEINLINE bf_read( const void *pData, int nBytes, int nBits = -1 ) : bc( pData, nBytes, nBits )									  \
	{																														  \
	}																														  \
																															  \
	FORCEINLINE bf_read( const char *pDebugName, const void *pData, int nBytes, int nBits = -1 ) : bc( pDebugName, pData, nBytes, nBits ) \
	{																														  \
	}																														  \
};

#define BITS_PER_INT		32
inline int GetBitForBitnum(int bitNum)
{
	static int bitsForBitnum[] =
	{
		(1 << 0),
		(1 << 1),
		(1 << 2),
		(1 << 3),
		(1 << 4),
		(1 << 5),
		(1 << 6),
		(1 << 7),
		(1 << 8),
		(1 << 9),
		(1 << 10),
		(1 << 11),
		(1 << 12),
		(1 << 13),
		(1 << 14),
		(1 << 15),
		(1 << 16),
		(1 << 17),
		(1 << 18),
		(1 << 19),
		(1 << 20),
		(1 << 21),
		(1 << 22),
		(1 << 23),
		(1 << 24),
		(1 << 25),
		(1 << 26),
		(1 << 27),
		(1 << 28),
		(1 << 29),
		(1 << 30),
		(1 << 31),
	};

	return bitsForBitnum[(bitNum) & (BITS_PER_INT - 1)];
}

#if 0


#define DELEGATE0( t, m )	t m()					\
{												\
		Check(); \
	t nOld = old1.m();						\
	t nNew = new1.m();						\
	Assert( nOld == nNew );						\
	Check();									\
	return nOld;								\
}
#define DELEGATE1( t, m, t1 )	t m( t1 x)					\
{												\
		Check(); \
	t nOld = old1.m( x);						\
	t nNew = new1.m( x );						\
	Assert( nOld == nNew );						\
	Check();									\
	return nOld;								\
}

#define DELEGATE0I( m )	DELEGATE0( int, m )
#define DELEGATE0LL( m ) DELEGATE0( int64, m )

class bf_read
{
	old_bf_read old1;
	CBitRead new1;

	void Check(void) const
	{
		int n = new1.GetNumBitsRead();
		int o = old1.GetNumBitsRead();
		Assert(n == o);
		Assert(old1.IsOverflowed() == new1.IsOverflowed());
	}

public:
	FORCEINLINE bf_read(void) : old1(), new1()
	{
	}

	FORCEINLINE bf_read(const void* pData, int nBytes, int nBits = -1) : old1(pData, nBytes, nBits), new1(pData, nBytes, nBits)
	{
	}

	FORCEINLINE bf_read(const char* pDebugName, const void* pData, int nBytes, int nBits = -1) : old1(pDebugName, pData, nBytes, nBits), new1(pDebugName, pData, nBytes, nBits)
	{
	}

	FORCEINLINE bool IsOverflowed(void) const
	{
		bool bOld = old1.IsOverflowed();
		bool bNew = new1.IsOverflowed();
		Assert(bOld == bNew);
		Check();
		return bOld;

	}

	void ReadBits(void* pOut, int nBits)
	{
		old1.ReadBits(pOut, nBits);
		void* mem = stackalloc(1 + (nBits / 8));
		new1.ReadBits(mem, nBits);
		Assert(memcmp(mem, pOut, nBits / 8) == 0);
	}

	bool ReadBytes(void* pOut, int nBytes)
	{
		ReadBits(pOut, nBytes << 3);
		return !IsOverflowed();
	}


	unsigned int ReadUBitLong(int numbits)
	{
		unsigned int nOld = old1.ReadUBitLong(numbits);
		unsigned int nNew = new1.ReadUBitLong(numbits);
		Assert(nOld == nNew);
		Check();
		return nOld;
	}

	unsigned const char* GetBasePointer()
	{
		Assert(old1.GetBasePointer() == new1.GetBasePointer());
		Check();
		return old1.GetBasePointer();
	}
	void SetDebugName(const char* pDebugName)
	{
		old1.SetDebugName(pDebugName);
		new1.SetDebugName(pDebugName);
		Check();
	}

	void StartReading(const void* pData, int nBytes, int iStartBit = 0, int nBits = -1)
	{
		old1.StartReading(pData, nBytes, iStartBit, nBits);
		new1.StartReading(pData, nBytes, iStartBit, nBits);
		Check();
	}

	void SetAssertOnOverflow(bool bAssert)
	{
		old1.SetAssertOnOverflow(bAssert);
		//		new1.SetAssertOnOverflow( bAssert );
		Check();
	}

	DELEGATE0I(ReadOneBit);
	DELEGATE0I(ReadByte);
	DELEGATE0I(ReadWord);
	DELEGATE0I(ReadLong);
	DELEGATE0I(GetNumBytesLeft);
	DELEGATE0I(ReadShort);
	DELEGATE1(int, PeekUBitLong, int);
	DELEGATE0I(ReadChar);
	DELEGATE0I(GetNumBitsRead);
	DELEGATE0LL(ReadLongLong);
	DELEGATE0(float, ReadFloat);
	DELEGATE0(unsigned int, ReadUBitVar);
	DELEGATE0(float, ReadBitCoord);
	DELEGATE2(float, ReadBitCoordMP, bool, bool);
	DELEGATE0(float, ReadBitFloat);
	DELEGATE0(float, ReadBitNormal);
	DELEGATE1(bool, Seek, int);
	DELEGATE1(float, ReadBitAngle, int);
	DELEGATE1(bool, SeekRelative, int);
	DELEGATE0I(GetNumBitsLeft);
	DELEGATE0I(TotalBytesAvailable);

	void SetOverflowFlag()
	{
		old1.SetOverflowFlag();
		new1.SetOverflowFlag();
		Check();
	}

	bool ReadString(char* pStr, int bufLen, bool bLine = false, int* pOutNumChars = NULL)
	{
		Check();
		int oldn, newn;
		bool bOld = old1.ReadString(pStr, bufLen, bLine, &oldn);
		bool bNew = new1.ReadString(pStr, bufLen, bLine, &newn);
		Assert(bOld == bNew);
		Assert(oldn == newn);
		if (pOutNumChars)
			*pOutNumChars = oldn;
		Check();
		return bOld;
	}

	bool ReadWString(wchar_t* pStr, int bufLen, bool bLine = false, int* pOutNumChars = NULL)
	{
		Check();
		int oldn, newn;
		bool bOld = old1.ReadWString(pStr, bufLen, bLine, &oldn);
		bool bNew = new1.ReadWString(pStr, bufLen, bLine, &newn);
		Assert(bOld == bNew);
		Assert(oldn == newn);
		if (pOutNumChars)
			*pOutNumChars = oldn;
		Check();
		return bOld;
	}

	void ReadBitVec3Coord(Vector& fa)
	{
		Check();
		old1.ReadBitVec3Coord(fa);
		Vector test;
		new1.ReadBitVec3Coord(test);
		Assert(VectorsAreEqual(fa, test));
		Check();
	}
	void ReadBitVec3Normal(Vector& fa)
	{
		Check();
		old1.ReadBitVec3Coord(fa);
		Vector test;
		new1.ReadBitVec3Coord(test);
		Assert(VectorsAreEqual(fa, test));
		Check();
	}

	char* ReadAndAllocateString(bool* pOverflow = NULL)
	{
		Check();
		bool bold, bnew;
		char* pold = old1.ReadAndAllocateString(&bold);
		char* pnew = new1.ReadAndAllocateString(&bnew);
		Assert(bold == bnew);
		Assert(strcmp(pold, pnew) == 0);
		delete[] pnew;
		Check();
		if (pOverflow)
			*pOverflow = bold;
		return pold;

	}

	DELEGATE1(int, ReadSBitLong, int);

};
#endif


WRAP_READ(CBitRead);
#pragma warning( pop ) 
#endif


